/*	--- 装饰器 --- 


#	动态地给一个【对象】添加一些【额外的职责】。

就【增加功能】来说，相比【生成子类】更为灵活。

==================================================


【装饰器（Decorator）模式】，是一种在【运行期】动态给【某个对象的实例】增加功能的方法。

我们在【IO 的 Filter模式】一节中其实已经讲过【装饰器模式】了。

在Java标准库中，InputStream是【抽象类】，FileInputStream、ServletInputStream、Socket.getInputStream()这些InputStream都是【最终数据源】。


现在，如果要给【不同的最终数据源】增加【缓冲功能】、【计算签名功能】、【加密解密功能】，那么，【3个最终数据源】、【3种功能】一共需要【9个子类】。

如果【继续增加】最终数据源，或者【增加新功能】，【子类会爆炸式增长】，这种设计方式显然是【不可取】的。


-----------------


【Decorator模式】的目的就是把【一个一个的附加功能】，用【Decorator的方式】给【一层一层地累加】到【原始数据源】上，最终，通过【组合】获得【我们想要的功能】。


例如：给 FileInputStream 增加【缓冲和解压缩功能】， 
用【Decorator模式】写出来如下： */

// 创建【原始的数据源】
InputStream fis = new FileInputStream("test.gz");
// 增加【缓冲功能】
InputStream bis = new BufferedInputStream(fis);
// 增加【解压缩功能】
InputStream gis = new GZIPInputStream(bis);


/*
或者一次性写成这样： */
InputStream input = new GZIPInputStream( // 第二层Decorator
	new BufferedInputStream( // 第一层Decorator
		new FileInputStream("test.gz") // 核心功能
	)
);


/*
观察 BufferedInputStream 和 GZIPInputStream , 它们实际上都是从 FilterInputStream继承的，这个 FilterInputStream 就是一个【抽象的Decorator】。

我们用【图】把【Decorator模式】画出来如下：

             ┌───────────┐
             │ Component │
             └───────────┘
                   ▲
      ┌────────────┼─────────────────┐
      │            │                 │
┌───────────┐┌───────────┐     ┌───────────┐
│ComponentA ││ComponentB │...  │ Decorator │
└───────────┘└───────────┘     └───────────┘
                                     ▲
                              ┌──────┴──────┐
                              │             │
                        ┌───────────┐ ┌───────────┐
                        │DecoratorA │ │DecoratorB │...
                        └───────────┘ └───────────┘


最顶层的【Component是接口】，对应到【IO】的就是 【InputStream这个抽象类】。

ComponentA、ComponentB是【实际的子类】，对应到IO的就是【FileInputStream、ServletInputStream这些数据源】。

【Decorator】是用于实现【各个附加功能的抽象装饰器】，对应到【IO】的就是【FilterInputStream】。

而从【Decorator派生】的就是一个一个的【装饰器】，它们【每个】都有【独立的功能】，对应到【IO】的就是【BufferedInputStream、GZIPInputStream等】。


-------------------


Q: 【Decorator模式】有什么好处？
A: 它实际上把【核心功能】和【附加功能】给分开了。

【核心功能】指【FileInputStream这些真正读数据的源头】，【附加功能】指【加缓冲、压缩、解密】这些功能。

如果我们要新增【核心功能】，就增加【Component的子类】，例如【ByteInputStream】。

如果我们要增加【附加功能】，就增加【Decorator的子类】，例如【CipherInputStream】。

【两部分】都可以【独立地扩展】，而具体【如何附加功能】，由【调用方】自由组合，从而极大地增强了【灵活性】。


---------------------------


Q: 如果我们要自己设计【完整的Decorator模式】，应该如何设计？

我们还是举个栗子：假设我们需要【渲染】一个【HTML的文本】，但是【文本】还可以【附加一些效果】，比如【加粗、变斜体、加下划线等】。

A: 为了实现【动态附加效果】，可以采用【Decorator模式】。

首先，仍然需要定义【顶层接口TextNode】： */
public interface TextNode {
	// 设置text
	void setText(String text);

	// 获取text
	String getText();
}


/*
对于【核心节点】，例如"<span>"，它需要从【TextNode】直接继承： */
public class SpanNode implements TextNode {
	private String text;

	public void setText(String text) {
		this.text = text;
	}

	public String getText() {
		return "<span>" + text + "</span>";
	}
}


/*
紧接着，为了实现【Decorator模式】，需要有一个【抽象的Decorator类】： */
public abstract class NodeDecorator implements TextNode {
	protected final TextNode target;  

	protected NodeDecorator(TextNode target) {
		this.target = target; // init TextNode
	}

	public void setText(String text) {
		this.target.setText(text);
	}
}
/*
这个【NodeDecorator类】的核心是【持有一个interface TextNode】，

即将要用的【功能】附加到的【TextNode实例】。

---------------


接下来就可以写一个【加粗功能】： */
public class BoldDecorator extends NodeDecorator {
	
	public BoldDecorator(TextNode target) {
		super(target);
	}

	public String getText() {
		return "<b>" + target.getText() + "</b>";
	}
}


/*
类似的，可以继续加【ItalicDecorator、UnderlineDecorator等】。

----------------

【客户端】可以【自由组合】这些【Decorator】： */
TextNode n1 = new SpanNode();
TextNode n2 = new BoldDecorator(new UnderLineDecorator(new SpanNode()));
TextNode n3 = new ItalicDecorator(new BoldDecorator(new SpanNode()));

n1.setText("Hello");
n2.setText("Decorated")
n3.setText("World");

System.out.println(n1.getText);
	// <span>Hello</span>

System.out.println(n2.getText());
	// <b><u><span>Decorated</span></u></b>

System.out.println(n3.getText());
	// <i><b><span>World</span></b></i>



/*=======================================================


#	练习

使用【Decorator】添加一个【<del>标签】表【示删除】。  */






/*====================================================


#	----- 装饰器Decorator の 小结 -----


1. 使用【Decorator模式】，可以独立增加【核心功能】，也可以独立增加【附加功能】，二者互不影响；

2. 可以在【运行期】动态地给【核心功能】增加【任意个附加功能】。






*/






